#ifndef PARSEDDATA_H_
#define PARSEDDATA_H_

#include <string>
#include "parser/exceptions/InvalidDataException.h"
#include "util/LinkedList.h"
#include "map/MapLocation.h"
#include "map/Road.h"
#include "map/Map.h"

namespace parser {

/* @class ParsedData
 * Representacion de los datos parseados de un registro.
 *
 * Al parsear los datos de un registro, se pueden generar warnings. Estos son
 * errores corregibles y por lo tanto no deben interrumpir la ejecucion del
 * programa. Para eso ParsedData permite almacenar un listado de warnings
 * generados durante el parseo de este registro individual.
 */
class ParsedData {
public:
	/*
	 * Agrega un mensaje de warning al objeto
	 */
	ParsedData* addWarning(std::string message);
	/*
	 * Recupera el siguiente warning de la lista.
	 */
	std::string getNextWarning();
	virtual ~ParsedData() {
		while(!warnings.isEmpty()) delete warnings.removeFirst();
	}
	/*
	 * Devuelve si se generaron menasajes de error durante la carga.
	 */
	bool hasWarnings();
	/*
	 * Metodo para tener una representacion en std::string del objeto.
	 */
	virtual std::string toString() = 0;

protected:
	util::LinkedList<std::string> warnings; // listado con los warnings ocurridos
};

class IntersectionParsedData: public ParsedData {
public:
	IntersectionParsedData();
	virtual ~IntersectionParsedData();

	// getters
	double getX();
	double getY();
	std::string getId();

	// setters
	IntersectionParsedData* setX(double x);
	IntersectionParsedData* setY(double y);
	IntersectionParsedData* setId(std::string id) throw (InvalidDataException);

	virtual std::string toString();

private:
	double x; // posicion X del vertice
	double y; // posicion Y del vertice
	std::string id; // identificador del vertice
};

class RoadParsedData: public ParsedData {
public:
	RoadParsedData();
	virtual ~RoadParsedData();

	// getters
	std::string getId();
	double getLength();
	double getMaxSpeed();
	std::string getIdO();
	std::string getIdD();
	std::string getRoadName();
	int getInitialNumber();
	int getFinalNumber();
	RoadType getRoadType();

	// setters
	RoadParsedData* setId(std::string id) throw (InvalidDataException);
	RoadParsedData* setLength(double length);
	RoadParsedData* setMaxSpeed(double maxSpeed) throw (InvalidDataException);
	RoadParsedData* setIdO(std::string idO) throw (InvalidDataException);
	RoadParsedData* setIdD(std::string idD) throw (InvalidDataException);
	RoadParsedData* setRoadName(std::string roadName) throw (InvalidDataException);
	RoadParsedData* setRoadNumbersRange(std::string roadNumberRange) throw (InvalidDataException);
	RoadParsedData* setRoadType(std::string roadType) throw (InvalidDataException);

	virtual std::string toString();

private:
	std::string id; // id de la arista
	double length; // longitud de la arista
	double maxSpeed; // velocidad maxima de la arista
	std::string idO; // identificador del vertice de origen
	std::string idD; // identificador del vertice de destino
	std::string roadName; // nombre del camino
	int initialNumber; // altura inicial del camino
	int finalNumber; // altura final del camino
	RoadType roadType; // tipo de camino
};

class MapLocationParsedData: public ParsedData {
public:
	/*
	 * Constructor por defecto. No recibe parametros.
	 */
	MapLocationParsedData();

	/*
	 * Destructor.
	 */
	virtual ~MapLocationParsedData();

	// getters
	virtual std::string getId();

	virtual std::string getRoadId();

	virtual int getNumber();

	virtual MapLocationType getType();

	// setters
	virtual MapLocationParsedData* setId(std::string id)
			throw (InvalidDataException);

	virtual MapLocationParsedData* setRoadId(std::string id)
			throw (InvalidDataException);

	virtual MapLocationParsedData* setNumber(int i)
			throw (InvalidDataException);

	virtual MapLocationParsedData* setType(std::string type)
			throw (InvalidDataException);

	virtual MapLocationParsedData* setType(MapLocationType type);

	virtual std::string toString();

private:
	std::string id;
	std::string roadId;
	int number;
	MapLocationType type;
};

class ConfigEntryParsedData: public ParsedData {
public:
	/*
	 * Constructor por defecto.
	 */
	ConfigEntryParsedData();

	/*
	 * Destructor.
	 */
	virtual ~ConfigEntryParsedData();

	// getters
	virtual std::string getKey();
	virtual std::string getValue();

	// setters
	virtual ConfigEntryParsedData* setKey(std::string key)
			throw (InvalidDataException);
	virtual ConfigEntryParsedData* setValue(std::string value)
			throw (InvalidDataException);

	virtual std::string toString();

private:
	std::string key;
	std::string value;
};

} // end of namespace

#endif /* PARSEDDATA_H_ */
